package com.motu.monstercity.server.gate;

import com.google.protobuf.Message.Builder;
import com.motu.monstercity.protocol.CmdEnum;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ProtobufManager {

    private static final Logger logger = LoggerFactory.getLogger(ProtobufManager.class);

    /**
     * 获取命令获取协议参数类
     */
    public static Class<?> getRequestClass(String cmd) {
        try {
            String protobufName = getProtobufNameByCmd(cmd);
            Class<?> classType = Class.forName("com.motu.underground.protocol." + protobufName);// 先获取主类
            Class innerClazz[] = classType.getDeclaredClasses();
            for (Class cls : innerClazz) {// 遍历所有内部类
                // com.motu.underground.protocol.CsGameInvest$CSGameInvestClickRequest
                String requestName = getRequestNameByCmd(cmd);
                if (cls.getName().split("\\$")[1].equals(requestName)) {
                    return cls;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取命令获取协议范湖类
     */
    public static Class<?> getReponseClass(String cmd) {
        String protobufName = getProtobufNameByCmd(cmd);
        String responseName = "";
        try {
            Class<?> classType = Class.forName("com.motu.underground.protocol." + protobufName);// 先获取主类
            Class innerClazz[] = classType.getDeclaredClasses();
            for (Class cls : innerClazz) {// 遍历所有内部类
                // com.motu.underground.protocol.CsGameInvest$CSGameInvestClickRequest
                responseName = getReponseNameByCmd(cmd);
                if (cls.getName().split("\\$")[1].equals(responseName)) {
                    return cls;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        logger.error("getReponseClass error cmd:"+cmd+" protobufName:"+protobufName+" responseName:"+responseName);
        return null;
    }

    /**
     * 获取命令获取协议参数类
     */
    public static Builder getRequestBuild(String cmd) {
        try {
            Class<?> classType = getRequestClass(cmd);
            Method method = classType.getMethod("newBuilder"); // newBuilder 为静态变量，即使没有 message 的具体实例也可以 invoke
            Object obj = method.invoke(null, new Object[] {});
            Builder builder = (Builder) obj; // 得到 builder
            return builder;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取命令获取协议参数类
     */
    public static Builder getResponseBuild(String cmd) {
        try {
            Class<?> classType = getReponseClass(cmd);
            Method method = classType.getMethod("newBuilder"); // newBuilder 为静态变量，即使没有 message 的具体实例也可以 invoke
            Object obj = method.invoke(null, new Object[] {});
            Builder builder = (Builder) obj; // 得到 builder
            return builder;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static JsonArray getCmdList() {
        JsonArray jsonArray = new JsonArray();
        for (CmdEnum.EnumCmdID e : CmdEnum.EnumCmdID.values()) {
            try {
                JsonObject jsonObject = new JsonObject();
                Class<CmdEnum.EnumCmdID> clazz = CmdEnum.EnumCmdID.class;
                if (e.toString().equals("UNRECOGNIZED")) {
                    continue;
                }
                Field field = clazz.getDeclaredField(e.toString() + "_VALUE");
                int code = field.getInt(CmdEnum.EnumCmdID.class);
                if (code >= 70100 && code < 80000) {
                    System.out.println(e.toString() + "_" + e.ordinal() + "_" + code);
                    jsonObject.put("cmd", e.toString());// 协议名称
                    jsonObject.put("code", code);// 协议编号
                    jsonArray.add(jsonObject);
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
        return jsonArray;
    }

    public static JsonArray getParams(String cmd) {
        Class<?> classType = getRequestClass(cmd);
        if (classType == null) {
            return new JsonArray();
        }
        Field[] field = classType.getDeclaredFields();
        JsonArray jsonArray = new JsonArray();
        for (int j = 0; j < field.length; j++) { // 遍历所有属性
            String fieldName = field[j].getName(); // 获取属性的名字
            if (fieldName.substring(fieldName.length() - 1, fieldName.length()).equals("_")) {
                JsonObject jsonObject = new JsonObject();
                String name = fieldName.substring(0, fieldName.length() - 1);
                System.out.println("cmd = " + cmd + " attribute name:" + name);
                // fieldName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); // 将属性的首字符大写，方便构造get，set方法
                String type = field[j].getGenericType().toString(); // 获取属性的类型
                System.out.println("cmd = " + cmd + " attribute type:" + type);
                jsonObject.put("name", name);// 字段名称
                jsonObject.put("type", type);// 字段类型
                jsonArray.add(jsonObject);
            }
        }
        return jsonArray;
    }

    /**
     * 根据命令名称获取模块关键字
     */
    public static String getKeyByCmd(String cmd) {
        String[] cmds = cmd.split("_");
        String key = cmds[2];// 关键字
        return changeFirstUpper(key);
    }

    /**
     * 转成首字母大写
     */
    public static String changeFirstUpper(String name) {
        name = name.toLowerCase();// 转成小写
        name = name.substring(0, 1).toUpperCase() + name.substring(1);// 首字母大写
        return name;
    }

    /**
     * 根据命令名称获取Handler类名
     */
    public static String getHandlerNameByCmd(String cmd) {
        return getKeyByCmd(cmd) + "Handler";
    }

    /**
     * 根据命令名称获取Protobuf类名
     */
    public static String getProtobufNameByCmd(String cmd) {
        return "CsGame" + getKeyByCmd(cmd);
    }

    /**
     * 根据命令名称获取Request类名
     */
    public static String getRequestNameByCmd(String cmd) {
        // CMD_GAME_INVEST_COMPANY_REFUSE_WORK
        // CSGameInvestCompanyRefuseWorkRequest
        String name = "CS";
        String[] cmds = cmd.split("_");
        for (int i = 1; i < cmds.length; i++) {
            name += changeFirstUpper(cmds[i]);
        }
        return name + "Request";
    }

    /**
     * 根据命令名称获取Reponse类名
     */
    public static String getReponseNameByCmd(String cmd) {
        // CMD_GAME_INVEST_COMPANY_REFUSE_WORK
        // CSGameInvestCompanyRefuseWorkRequest
        String name = "CS";
        String[] cmds = cmd.split("_");
        for (int i = 1; i < cmds.length; i++) {
            name += changeFirstUpper(cmds[i]);
        }
        return name + "Response";
    }

}
